#if defined(_MSC_VER)
#include "SDL.h"
#else
#include "SDL/SDL.h"
#endif

#include "Font.h"

Font::Font(void)
{
	m_pFontSurface = NULL;
}

Font::~Font(void)
{
	if ( m_pFontSurface != NULL )
		SDL_FreeSurface( m_pFontSurface );
	m_pFontSurface = NULL;
}


// Load the font from the bmp file
// Assumes the image for each character is square and the characters are one above another.
void Font::Load(const char* pFileName, SDL_PixelFormat *pPixelFormat)
{
	SDL_Surface *pTempSurface = SDL_LoadBMP("font.bmp");
	if ( pTempSurface == NULL )
	{
		printf("Unable to open font file : font.bmp\n" );
		m_pFontSurface = NULL;
		return;
	}

	// Convert the surface to a format we can use
	m_pFontSurface = SDL_ConvertSurface(pTempSurface, pPixelFormat, SDL_SWSURFACE);
	// And free the original
	SDL_FreeSurface(pTempSurface);

	if (SDL_MUSTLOCK(m_pFontSurface))
		if (SDL_LockSurface(m_pFontSurface) < 0) 
			return;

	// Assumes characters are in a square area, so height is equal to bitmap width
	int iBMPCharacterSize = m_pFontSurface->w;
	// Thus number of characters is total height divided by character height
	int iNumberCharacters = m_pFontSurface->h / iBMPCharacterSize;
	// Number of ints per scan line is the number of bytes divided by size of an int
	int iUIntsPerScanLine = m_pFontSurface->pitch / sizeof(unsigned int); // Bytes per scanline divided by size of an unsigned int

	int iCharNum, iX, iY;

	unsigned int uiThreshold = 0xA0;

	// Calculate the width and start position of each character
	for (iCharNum = 0; iCharNum < iNumberCharacters; iCharNum++)
	{
		m_pFontOfs[iCharNum] = iBMPCharacterSize;
		m_pFontWidth[iCharNum] = 0;
		for (iY = 0; iY < iBMPCharacterSize; iY++)
		{
			for (iX = 0; iX < iBMPCharacterSize; iX++)
			{
				// Look for the first pixel for the start offset of the character, and last pixel for the width.
				unsigned int uiPixelValue = ((unsigned int*)m_pFontSurface->pixels)[(iY + iCharNum * iBMPCharacterSize) * iUIntsPerScanLine + iX];
				if ( uiPixelValue != 0) 
				{
					int iNewPixelValue = 0;
					if ( ( (uiPixelValue & 0xff) > uiThreshold )
						|| ( (uiPixelValue>>8 & 0xff) > uiThreshold )
						|| ( (uiPixelValue>>16 & 0xff) > uiThreshold ) )
					{
						iNewPixelValue = 0xffffff;
					}

					((unsigned int*)m_pFontSurface->pixels)[(iY + iCharNum * iBMPCharacterSize) * iUIntsPerScanLine + iX] = iNewPixelValue;

					if (iX < m_pFontOfs[iCharNum])
						m_pFontOfs[iCharNum] = iX;

					if (iX > m_pFontWidth[iCharNum])
						m_pFontWidth[iCharNum] = iX;
				}
			}
		}
		m_pFontWidth[iCharNum] -= m_pFontOfs[iCharNum] -1;
		m_pFontWidth[iCharNum] ++; // Enforce a gap between characters
	}

	// Unlock if needed
	if (SDL_MUSTLOCK(m_pFontSurface)) 
		SDL_UnlockSurface(m_pFontSurface);
}


void Font::DrawString(SDL_Surface *pScreen, int iX, int iY, const char* pText, unsigned int uiColour )
{
	// If we have no font loaded then we can do nothing :(
	if ( m_pFontSurface == NULL )
		return;

	// Lock surface if needed
	if (SDL_MUSTLOCK(m_pFontSurface))
		if (SDL_LockSurface(m_pFontSurface) < 0) 
			return;

	const char* pCharacter = pText;
	while (*pCharacter != 0)
	{
		if (*pCharacter == ' ')
			iX += m_pFontSurface->w / 2;
		else
		{
			iX += DrawCharacter(pScreen, iX, iY, *pCharacter, uiColour);
		}
		pCharacter++; // Advance to next character in the string
	}

	// Unlock if needed
    if (SDL_MUSTLOCK(m_pFontSurface)) 
        SDL_UnlockSurface(m_pFontSurface);
}

int Font::DrawCharacter(SDL_Surface *pScreen, int iXStart, int iYStart, int iCharacter, unsigned int uiColour )
{
	// If we have no font loaded then we can do nothing :(
	if ( m_pFontSurface == NULL )
		return 0;

	iCharacter -= 33;
	if ( iCharacter < 0 )
		return 0; // Unprintable.

	int iRed = (uiColour & 0xff0000) >> 16;
	int iGreen = (uiColour & 0x00ff00) >> 8;
	int iBlue = (uiColour & 0x0000ff);
	int iR, iG, iB;

	int iX, iY;
	for (iY = 0; iY < m_pFontSurface->w; iY++)
	{
		int iScreenOffset = iXStart + (iYStart + iY) * (pScreen->pitch / sizeof(unsigned int));
		int iCharOffset = (iY + iCharacter * m_pFontSurface->w) * (m_pFontSurface->pitch / sizeof(unsigned int)) + m_pFontOfs[iCharacter];
		for (iX = 0; iX < m_pFontWidth[iCharacter]; iX++)
		{
			unsigned int uiFontPixelValue = ((unsigned int*)m_pFontSurface->pixels)[iCharOffset];
			if ( uiFontPixelValue > 0 )
			{
				((unsigned int*)pScreen->pixels)[iScreenOffset] = uiColour;
			}
			iScreenOffset++;
			iCharOffset++;
		}
	}
	return m_pFontWidth[iCharacter];
}

